package org.r13notes.activity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.r13notes.R;
import org.r13notes.notes.Note;
import org.r13notes.notes.NotesContainer;
import org.r13notes.notes.NotesDBUserAdapter;
import org.r13notes.view.NotesListView;

import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnPreDrawListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.TextView;

/**
 * 
 * @author Lukasz Raczko
 *
 * Main activity of application. It shows list of notes, as well as buttons to add/remove notes and options.
 */

public class R13notesActivity extends BaseActivity {
	
	@Override
	public void onResume() {
		super.onResume();
		
		/*
		 * get notes from database and put in adapter
		 */
		notesListAdapter.setNotes(dbAdapter.getNotes());	
		
	}
	
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
        setContentView(R.layout.main);
        
		dbAdapter = new NotesDBUserAdapter(this);
        
        List<Note> notes = new ArrayList<Note>();
        
        notesContainer = new NotesContainer(notes);
        
        NotesListView notesListView = (NotesListView) findViewById(R.id.mainNotesListView);
        notesListAdapter = new NotesListAdapter(this, R.layout.list_row, notes);
        notesListView.setAdapter(notesListAdapter);
        notesListView.setOnItemClickListener(new OnItemClickListener(){

			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
				notesListAdapter.setExpandViewValue(position);
				notesListAdapter.notifyDataSetChanged();
			}
        	
        });
        
        notesListView.setOnItemLongClickListener(new OnItemLongClickListener(){

			@Override
			public boolean onItemLongClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
				return false;
			}
        	
        });
        
    }
    
    protected class NotesListAdapter extends ArrayAdapter<Note>{
   	
		public NotesListAdapter(Context context, int textViewResourceId, List<Note> objects) {
			super(context, textViewResourceId, objects);
			this.id = textViewResourceId;
			this.notes = objects;
			this.expanded = new HashMap<String, Boolean>();
			this.numberOfLines = new HashMap<String, Integer>();
			this.context = context;
			fillMaps();
		}
		
		private void fillMaps(){
			for (Note n : notes){
				expanded.put(n.getNote(), false);
				numberOfLines.put(n.getNote(), 0);
			}
		}
		
		public void setExpandViewValue(int position){
			String key = notes.get(position).getNote();
			
			if (expanded.get(key)){
				expanded.put(key, false);							
			}
			else {
				expanded.put(key, true);								
			}
		}
		
		public void setNotes(List<Note> newNotes){
			this.notes.clear();
			this.notes.addAll(newNotes);
			fillMaps();
			this.notifyDataSetChanged();
		}
		
		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View actualRow = convertView;
			Note rowNote = notes.get(position);
			
			if (actualRow == null){
				LayoutInflater vi = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				actualRow = vi.inflate(id, null);
			}
			
			if (rowNote != null){
				final TextView text = (TextView) actualRow.findViewById(R.id.listRowText);
				final String noteText = rowNote.getNote();
				text.setText(noteText);
				
				/*
				 * If number of lines of that note is 0 in map then it means that it 
				 * still was not drawn onto the screen, so it is needed to create
				 * observer that will change that value and notify view to redraw
				 * with proper lines showing.
				 */				
				if (numberOfLines.get(noteText) == 0){
					ViewTreeObserver mainLayObserver = text.getViewTreeObserver();
										
			        mainLayObserver.addOnPreDrawListener(new OnPreDrawListener(){

						@Override
						public boolean onPreDraw() {
							
							numberOfLines.put(noteText, text.getLineCount());
			                
							notesListAdapter.notifyDataSetChanged();
							
			                ViewTreeObserver obs = text.getViewTreeObserver();
			                obs.removeOnPreDrawListener(this);
							
							return false;
						}
			        });		
				}
				
				/*
				 * When the nubmer of lines is known, it is time for managing displaying 
				 */
				else {
					TextView dots = (TextView) actualRow.findViewById(R.id.listRowDots);
				
					text.setMinLines(minimumLinesToShow);

					int count = numberOfLines.get(noteText);					

					/*
					 * If number of lines is bigger value than the number user has chosen and 
					 * whole note has NOT to be shown fully then set max lines to linesToShow value.
					 * Otherwise set default values.
					 */
					if (count > linesToShow && !expanded.get(noteText)){
						text.setMaxLines(linesToShow);		
						dots.setVisibility(View.VISIBLE);						
					}
					else {						
						text.setMaxLines(Integer.MAX_VALUE);	
						dots.setVisibility(View.GONE);					
					}
										
				}				
				
			}
			
			return actualRow;
		}		

		private List<Note> notes;
		
		/**
		 * Map which contains number of line of notes. Used to judge if
		 * note has to be shortened in display with second information 
		 * from expanded map, which contains information about clicks
		 * of user.
		 */
		private Map<String, Integer> numberOfLines;
		private Map<String, Boolean> expanded;
		
		private int id;
		private Context context;
    	
    }
    
    private NotesContainer notesContainer; 
    
    /**
     * Read from preferences - in onCreate, or changed after menu item selected. 
     * Contains information what type of sorting is done on list.
     * After drag and drop of any note it cam be changed to default if user approves
     * that actual state of list is the new default state.
     */
    private int notesSorting;
    
    /**
     * Number of lines in every row to be shown. Minimum is 2 to be able to click it with ease.
     * TODO read it from database. 
     */
    private int linesToShow = 2;
    
    /**
     * Number of min lines to show in view. Default is 2 to have ease with clicking on note.
     */
    private int minimumLinesToShow = 2;
    
    /**
     * Adapter for listView that contains all notes    
     */
    private NotesListAdapter notesListAdapter;
    
    /**
     * Adapter used to get and set information to database
     */
    private NotesDBUserAdapter dbAdapter;
    
    private static final int NOTES_NOT_SORTED = 0;
    private static final int NOTES_SORTED_BY_DATE = 1;
    private static final int NOTES_SORTED_BY_PRIORITY = 2;    
    
}